Skip to content

✨ Optimize ChatItem and StreamItem components and reduce rerender - #4

Merged
QuentinVdr merged 2 commits into
mainfrom
feat/FixRerenderIssues
Sep 17, 2025
Merged

✨ Optimize ChatItem and StreamItem components and reduce rerender#4
QuentinVdr merged 2 commits into
mainfrom
feat/FixRerenderIssues

Conversation

@QuentinVdr

@QuentinVdr QuentinVdr commented Sep 17, 2025

Copy link
Copy Markdown
Owner

… performance improvements

Summary by CodeRabbit

  • Bug Fixes

    • Stream and chat iframes now reliably reload when their source changes, preventing stale content.
    • Dark theme for chat applies consistently when toggled.
  • Refactor

    • Grid item components optimized to reduce unnecessary re-renders and improve UI responsiveness.

@coderabbitai

coderabbitai Bot commented Sep 17, 2025

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

Walkthrough

ChatItem and StreamItem components are now wrapped with React.memo and use case-insensitive prop comparators; ChatItem no longer uses useMemo for iframeSrc. GridItem adds key={iframeSrc} to its iframe. Imports updated to include memo; public exports unchanged.

Changes

Cohort / File(s) Summary
Memoized components
src/components/gridItems/ChatItem/ChatItem.tsx, src/components/gridItems/StreamItem/StreamItem.tsx
Wrap components with React.memo and add custom comparator(s) (case-insensitive streamName, plus isDarkThemePreferred for ChatItem). Update imports to include memo.
Iframe remount on source change
src/components/gridItems/GridItem/GridItem.tsx
Add key={iframeSrc} to the <iframe> to force unmount/remount when iframeSrc changes.
Inline iframeSrc computation
src/components/gridItems/ChatItem/ChatItem.tsx
Remove useMemo and compute iframeSrc inline with a ternary that appends &darkpopout when isDarkThemePreferred is true.

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant Parent as GridItem
  participant Stream as StreamItem (memo)
  participant Chat as ChatItem (memo)
  participant IFrame as <iframe>

  User->>Parent: change props (streamName / theme)
  Parent->>Stream: render(streamName)
  Parent->>Chat: render(streamName, isDarkThemePreferred)
  note over Stream,Chat: Memoized — re-render only if comparator detects change

  Parent->>IFrame: set src=iframeSrc, key=iframeSrc
  alt iframeSrc changed
    IFrame-->>IFrame: Unmount → Mount (fresh load)
  else iframeSrc unchanged
    IFrame-->>IFrame: No remount
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

I twitch my whiskers at memo's call,
Props judged gently, renders fall.
A tiny key makes frames restart,
Fresh HTML, a brand new start.
I hop away — performant and small. 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title correctly summarizes the primary intent of the changeset—optimizing ChatItem and StreamItem to reduce rerenders—and matches the PR’s memoization and related performance tweaks described in the diff. It is concise and communicates the main change clearly to reviewers. The only issues are stylistic: the leading emoji and the minor wording "reduce rerender" (plural/formatting), but these do not make the title misleading.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c3d8e8a and 964b3ad.

📒 Files selected for processing (2)
  • src/components/gridItems/ChatItem/ChatItem.tsx (2 hunks)
  • src/components/gridItems/StreamItem/StreamItem.tsx (1 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/components/gridItems/StreamItem/StreamItem.tsx (1)

14-15: SSR safety and URL hardening.

  • Guard window for SSR to avoid ReferenceError.
  • URL‑encode streamName to prevent malformed URLs/injection.

Apply:

-  const iframeSrc = `https://player.twitch.tv/?channel=${streamName}&parent=${window.location.hostname}`;
+  const parent = typeof window !== 'undefined' ? window.location.hostname : '';
+  const channel = encodeURIComponent(streamName);
+  const iframeSrc = `https://player.twitch.tv/?channel=${channel}&parent=${parent}`;

Optional (reduce remounts due to casing only):

-const StreamItem = memo(({ streamName }: StreamItemProps) => {
+const StreamItem = memo(({ streamName }: StreamItemProps) => {
   // ...
-});
+}, (prev, next) => prev.streamName.toLowerCase() === next.streamName.toLowerCase());

Confirm whether the app ever renders on the server. If yes, the guard is required to prevent hydration/runtime errors.

src/components/gridItems/ChatItem/ChatItem.tsx (1)

12-12: Make Twitch chat embed SSR-safe, URL-encode channel, and document dark-mode param

  • Guard access to window and use encodeURIComponent(streamName); keep dark mode flag but note darkpopout is undocumented (still works); prefer documented theme=dark on the Everything embed when feasible.

Apply:

-  const iframeSrc = `https://www.twitch.tv/embed/${streamName}/chat?parent=${window.location.hostname}${isDarkThemePreferred ? '&darkpopout' : ''}`;
+  const parent = typeof window !== 'undefined' ? window.location.hostname : '';
+  const channel = encodeURIComponent(streamName);
+  const themeParam = isDarkThemePreferred ? '&darkpopout' : '';
+  const iframeSrc = `https://www.twitch.tv/embed/${channel}/chat?parent=${parent}${themeParam}`;

Optional memo comparator to avoid rerenders on casing-only changes:

-const ChatItem = memo(({ streamName, isDarkThemePreferred = false }: ChatItemProps) => {
+const ChatItem = memo(({ streamName, isDarkThemePreferred = false }: ChatItemProps) => {
   // ...
-});
+}, (prev, next) =>
+  prev.isDarkThemePreferred === next.isDarkThemePreferred &&
+  prev.streamName.toLowerCase() === next.streamName.toLowerCase()
+);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a6f9b2f and c3d8e8a.

📒 Files selected for processing (3)
  • src/components/gridItems/ChatItem/ChatItem.tsx (2 hunks)
  • src/components/gridItems/GridItem/GridItem.tsx (1 hunks)
  • src/components/gridItems/StreamItem/StreamItem.tsx (2 hunks)
🔇 Additional comments (3)
src/components/gridItems/GridItem/GridItem.tsx (1)

35-35: Keying iframe to src: LGTM; confirm intended UX on every src change.

Forces a full remount (resets scroll/focus/state) whenever iframeSrc changes, which is likely desired for hard refreshes. Just confirm this is acceptable for theme/param-only changes too.

src/components/gridItems/StreamItem/StreamItem.tsx (1)

9-25: Memoization: LGTM.

Wrapping with memo is appropriate; props are stable and this should reduce needless rerenders.

src/components/gridItems/ChatItem/ChatItem.tsx (1)

10-19: Memoization: LGTM.

Consistent with StreamItem; good for avoiding needless rerenders.

@QuentinVdr
QuentinVdr merged commit 30ce78b into main Sep 17, 2025
2 of 3 checks passed
@QuentinVdr
QuentinVdr deleted the feat/FixRerenderIssues branch September 17, 2025 17:55
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant